package com.doordu.soa.service.comm.utils;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.doordu.soa.service.comm.constant.DoorDuRedisKeyConstant;
import com.doordu.soa.service.comm.realm.FlowUserRealm;
import com.doordu.soa.service.comm.redis.RedisDoorduTemplate;
import com.google.common.net.InetAddresses;

/***
 * 权限判断的工具类,用于获取当前用户以及鉴权
 * 
 * @author kyler.tang
 *
 */
public class AuthUtils {

	public static final String USER_REALM_KEY = "_currUser";
	private static Logger log = LoggerFactory.getLogger(AuthUtils.class);

	public static String SHA1(String decript) {
		try {
			MessageDigest digest = java.security.MessageDigest.getInstance("SHA-1");
			digest.update(decript.getBytes());
			byte messageDigest[] = digest.digest();
			// Create Hex String
			StringBuffer hexString = new StringBuffer();
			// 字节数组转换为 十六进制 数
			for (int i = 0; i < messageDigest.length; i++) {
				String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
				if (shaHex.length() < 2) {
					hexString.append(0);
				}
				hexString.append(shaHex);
			}
			return hexString.toString();

		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return "";
	}

	/***
	 * 获取当前的请求信息.非请求线程无法获取请求.请注意使用的区域
	 * 
	 * @return
	 */
	public static HttpServletRequest getCurrRequest() {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		return request;
	}

	/**
	 * 利用MD5进行加密,//md5(substr(md5($password), 0, -6) + $salt);
	 * 
	 * @param password
	 *            待加密的字符串
	 * @param random6Number
	 *            盐
	 * @return 加密后的字符串
	 * @throws NoSuchAlgorithmException
	 *             没有这种产生消息摘要的算法
	 * @throws UnsupportedEncodingException
	 */
	public static String EncoderByMd5(String password, String random6Number)
			throws NoSuchAlgorithmException, UnsupportedEncodingException {
		// 确定计算方法
		MessageDigest md5 = MessageDigest.getInstance("MD5");
		// 加密
		String md5Pwd = BytesConvertToHexString(md5.digest(password.getBytes()));
		// 加密后密码，进行后6位替换
		String prePwd = md5Pwd.substring(0, md5Pwd.length() - 6)
				+ (StringUtils.isEmpty(random6Number) ? getRandomIntegerString(6) : random6Number);
		String postPwd = BytesConvertToHexString(md5.digest(prePwd.getBytes()));
		return postPwd;
	}

	/**
	 * 把字节数组转化成字符串返回
	 * 
	 * @param bytes
	 * @return
	 */
	public static String BytesConvertToHexString(byte[] bytes) {
		StringBuffer sb = new StringBuffer();
		for (byte aByte : bytes) {
			String s = Integer.toHexString(0xff & aByte);
			if (s.length() == 1) {
				sb.append("0" + s);
			} else {
				sb.append(s);
			}
		}
		return sb.toString();
	}

	/**
	 * 判断用户密码是否正确
	 * 
	 * @param newpasswd
	 *            用户输入的密码
	 * @param oldpasswd
	 *            数据库中存储的密码－－用户密码的摘要
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws UnsupportedEncodingException
	 */
	public static boolean checkpassword(String newpasswd, String random6Number, String oldpasswd)
			throws NoSuchAlgorithmException, UnsupportedEncodingException {
		if (EncoderByMd5(newpasswd, random6Number).equals(oldpasswd))
			return true;
		else
			return false;
	}

	/**
	 * 
	 * @Title: getRandomIntegerString @Description: number位随机数 @param @param
	 * number @param @return 参数 @return String 返回类型 @throws
	 */
	public static String getRandomIntegerString(int number) {
		long length = 1;
		for (int i = 0; i < number; i++) {
			length *= 10;
		}
		return String.valueOf(Math.round(Math.random() * length));
	}

	public static String md5Encode(String str) {
		try {
			// 生成一个MD5加密计算摘要
			MessageDigest md = MessageDigest.getInstance("MD5");
			// 计算md5函数
			md.update(str.getBytes());
			// digest()最后确定返回md5 hash值，返回值为8为字符串。因为md5 hash值是16位的hex值，实际上就是8位的字符
			// BigInteger函数则将8位的字符串转换成16位hex值，用字符串来表示；得到字符串形式的hash值
			return new BigInteger(1, md.digest()).toString(16);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	public static boolean isPrivateV4Address(String ip) {
		if (ip.equals("127.0.0.1"))
			return true;
		int address = InetAddresses.coerceToInteger(InetAddresses.forString(ip));
		return (((address >>> 24) & 0xFF) == 10)
				|| ((((address >>> 24) & 0xFF) == 172) && ((address >>> 16) & 0xFF) >= 16
						&& ((address >>> 16) & 0xFF) <= 31)
				|| ((((address >>> 24) & 0xFF) == 192) && (((address >>> 16) & 0xFF) == 168));
	}

	/**
	 * 获取综治平台当前登录的用户信息
	 * @param sessionId
	 * @return
	 */
	public static FlowUserRealm getFlowCurrentUser(String sessionId) {
		if(StringUtils.isBlank(sessionId)){
			return null;
		}

		String userRealmRedisKey = getLoginRedisKey(sessionId);
		RedisDoorduTemplate redisDoorduTemplate = SpringContextHolder.getBean(RedisDoorduTemplate.class);
		FlowUserRealm flowUserRealm = redisDoorduTemplate.get(userRealmRedisKey);
		if (flowUserRealm != null) {
			/** 刷新当前登录用户在redis中的存放时间 */
			redisDoorduTemplate.expire(userRealmRedisKey, DoorDuRedisKeyConstant.TIMEOUT_SEC_1800);

			/** 刷新当前登录用户所拥有的代理商集合在redis中的存放时间 */
			String agentsRedisKey = userRealmRedisKey+DoorDuRedisKeyConstant.FLOW_AGENTS_KEY;
			redisDoorduTemplate.expire(agentsRedisKey, DoorDuRedisKeyConstant.TIMEOUT_SEC_1800);
		}

		return flowUserRealm;
	}

	/**
	 * 获取综治平台当前登录的用户所拥有的代理商ID集合，包括自己
	 * @param sessionId
	 * @return
	 */
	public static List<Integer> getFlowCurrentUserHoldAgentIds(String sessionId) {
		if(StringUtils.isBlank(sessionId)){
			return null;
		}
		String userRealmRedisKey = getLoginRedisKey(sessionId);
		String agentsRedisKey = userRealmRedisKey+DoorDuRedisKeyConstant.FLOW_AGENTS_KEY;
		RedisDoorduTemplate redisDoorduTemplate = SpringContextHolder.getBean(RedisDoorduTemplate.class);
		List<Integer> list = redisDoorduTemplate.get(agentsRedisKey);
		if(list!=null){
			redisDoorduTemplate.expire(agentsRedisKey, DoorDuRedisKeyConstant.TIMEOUT_SEC_1800);
		}

		return list;
	}

	 public static  String getPermissionRedisKey(String sessionId) {
    	// key
        String permissionListKey = DoorDuRedisKeyConstant.DD_SOA_KEY + DoorDuRedisKeyConstant.PERMISSION_LIST_KEY + sessionId;
        return permissionListKey;
    }
    
	public static String getLoginRedisKey(String sessionId){
        String redisKey = DoorDuRedisKeyConstant.DD_SOA_KEY+DoorDuRedisKeyConstant.FLOW_LOGIN_KEY+sessionId;
        return redisKey;
    }
	
	public static String getGuidRedisKey(String guid){
        String redisKey = DoorDuRedisKeyConstant.DD_GUI_KEY+guid;
        return redisKey;
    }
	
	/**
	 * 强制下线综治登录用户
	 * @param userId
	 * @param msg 提示
	 * @param logger
	 */
	public static void forceOfflineFlowUser(Integer userId, String msg, Logger logger){
		String userRealmRedisKey=DoorDuRedisKeyConstant.DD_SOA_KEY+DoorDuRedisKeyConstant.FLOW_LOGIN_KEY;
		RedisDoorduTemplate redisDoorduTemplate = SpringContextHolder.getBean(RedisDoorduTemplate.class);
		Set<String> userKeys=redisDoorduTemplate.keys(userRealmRedisKey+"*");
		for(String key : userKeys){
			if(key.endsWith(DoorDuRedisKeyConstant.FLOW_AGENTS_KEY)){
				continue;
			}
			FlowUserRealm loginedUserRealm = redisDoorduTemplate.get(key);
			if(null!=loginedUserRealm && loginedUserRealm.getUserId().equals(userId)){
				loginedUserRealm.setForceOffline(true);//设置强制下线标识,拦截器会根据这个标识进行拦截，进而前端会有相应的提示
				loginedUserRealm.setForceOfflineMsg(msg);

				redisDoorduTemplate.set(key, loginedUserRealm);
				redisDoorduTemplate.expire(key, DoorDuRedisKeyConstant.TIMEOUT_SEC_60);
				String agentsRedisKey = key+DoorDuRedisKeyConstant.FLOW_AGENTS_KEY;
				redisDoorduTemplate.expire(agentsRedisKey, DoorDuRedisKeyConstant.TIMEOUT_SEC_60);
				if(logger!=null){
					logger.warn(msg+"-被强制挤下线key：{},{}", key, key+DoorDuRedisKeyConstant.FLOW_AGENTS_KEY);
				}
			}
		}
	}

	public static String getIpAddr(HttpServletRequest request){  
        String ipAddress = request.getHeader("x-forwarded-for");  
            if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {  
                ipAddress = request.getHeader("Proxy-Client-IP");  
            }  
            if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {  
                ipAddress = request.getHeader("WL-Proxy-Client-IP");  
            }  
            if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {  
                ipAddress = request.getRemoteAddr();  
                if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){  
                    //根据网卡取本机配置的IP  
                    InetAddress inet=null;  
                    try {  
                        inet = InetAddress.getLocalHost();  
                    } catch (UnknownHostException e) {  
                        e.printStackTrace();  
                    }  
                    ipAddress= inet.getHostAddress();  
                }  
            }  
            //对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割  
            if(ipAddress!=null && ipAddress.length()>15){ //"***.***.***.***".length() = 15  
                if(ipAddress.indexOf(",")>0){  
                    ipAddress = ipAddress.substring(0,ipAddress.indexOf(","));  
                }  
            }  
            return ipAddress;   
    }

	public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {
		System.out.println(EncoderByMd5("12345678", "001402"));
		// List<String> ipList = Arrays.asList("103.6.130.56", "8.8.8.8",
		// "10.0.2.33", "114.114.114.114");
		// Map<String, Boolean> ipb = new HashMap<>();
		// ipList.forEach((ip)->{
		// ipb.put(ip, isPrivateV4Address(ip));
		// });
		// System.out.println(ipb);

		// String str =
		// "access_token=933c74df9d8ac9853472785420114640&cmd=SingleChipUpdate&data=eyJpZCI6MzcsIm1kbGVuIjoicnJycnJyIiwidXJpIjoiaHR0cDovL2Rvb3JkdXN0b3JhZ2Uub3NzLWNuLXNoZW56aGVuLmFsaXl1bmNzLmNvbS9ycnJyciIsInZlcnNpb24iOiIxLjAifQ%3D%3D&timestamp=1487745305855&to_guid=BDD4001611-00006cba8a718f6fe9b4face4635c2a703346";
		// System.out.println(md5Encode(str));
		// System.out.println(string2MD5(str));
	}
}
